﻿using System;

namespace Web7.Dispose
{
    /// <summary>
    /// 安全处理一次性的非托管资源。
    /// </summary>
    public abstract class DisposableObject : IDisposable
    {
        private bool _disposed;
        private readonly static object DisposalLock = new object();

        /// <summary>
        /// 获取一个值，该值指示此实例是否被销毁。
        /// </summary>
        /// <value>
        /// 	<c>true</c> 如果此实例被销毁; 否则, <c>false</c>.
        /// </value>
        public bool IsDisposed
        {
            get { return _disposed; }
        }

        /// <summary>
        /// 执行与释放，释放或重置非托管资源相关的应用程序定义的任务。
        /// </summary>
        /// <filterpriority>2</filterpriority>
        public void Dispose()
        {
            Dispose(true);

            // SuppressFinalize用于这种类型的一个子类的情况下实现了终结。
            GC.SuppressFinalize(this);
        }

        ~DisposableObject()
        {
            // 运行处置，但让类知道这是由于终结运行。
            Dispose(false);
        }

        protected virtual void Dispose(bool disposing)
        {
            lock (DisposalLock)
            {
                // 如果尚未销毁，则return
                if (IsDisposed || !disposing) return;

                // Call to actually release resources. 此方法仅单独存放，使整个处理逻辑可以使用作为VS片段
                DisposeResources();

                // 标注该实例已被释放。
                _disposed = true;
            }
        }

        /// <summary>
        /// 处理处置资源。从抽象类派生 <see cref="DisposableObject"/>处理所需的锁定逻辑。
        /// </summary>
        protected abstract void DisposeResources();

        protected virtual void DisposeUnmanagedResources()
        {

        }
    }
}